package edu.hawaii.ics111.exam;

/**
 * A single exam question with its answers.
 * The answers are either multiple-choice (radio buttons)
 * or fill-in-the blank (text field).
 * Fill-in-the-blank questions may have more than one correct answer.
 * 
 * @author Branden Ogata
 *
 */

public class ExamQuestion extends ExamItem
{
  /**
   * The number of the question.
   * May not be necessary depending on later implementation.
   * 
   */
  private int number;
  
  /**
   * The question itself.
   * 
   */
  private String question;
  
  /**
   * The list of possible answers.
   * If only the first is non-null, then it is a fill-in-the-blank question.
   * 
   */
  private String[] answers;
  
  /**
   * The list of possible answers with the original regex.
   * Because actual regular expressions were not working, this uses different syntax.
   *   #[number]# where [number] is an integer indicates that there must be at least number spaces.
   *   #[number0],[number1]# where [number0] and [number1] are integers indicates that there must
   *     be at least number0 spaces, and that number1 spaces are preferred for stylistic reasons.
   * 
   */
  private String[] regexAnswers;
  
  /**
   * The index of the correct answer from the list of possible answers.
   * If -1, assume that the question is fill-in-the-blank.
   * (This may change depending on implementation.)
   * 
   */
  private int correct;

  /**
   * How many questions remain to be placed into a group.
   * If 0, then this is the last question of the group.
   * If -1, then this question is not in any group.
   * 
   */
  private int grouping;
  
  /**
   * Default constructor; this is never called in practice.
   * 
   */
  
  public ExamQuestion()
  {
    this.number = 0;
    this.question = "";
    this.answers = new String[] {""};
    this.correct = -1;
    this.grouping = -1;
  }
  
  /**
   * Initializes the instance variables for the question.
   * 
   * @param number The int equal to the question number.
   * @param question The String containing the question.
   * @param answers The String[] containing the answers for the question.
   * @param correct The int indicating the correct answer.
   * 
   */
  
  public ExamQuestion(int number, String question, String[] answers, int correct) 
  {
    this(number, question, answers, correct, -1);
  }

  /**
   * Initializes the instance variables for the question.
   * 
   * @param number The int equal to the question number.
   * @param question The String containing the question.
   * @param answers The String[] containing the answers for the question.
   * @param correct The int indicating the correct answer.
   * @param grouping The int indicating how many questions remain in a group of questions.
   * 
   */
  
  public ExamQuestion(int number, String question, String[] answers, int correct, int grouping) 
  {
    this.number = number;
    this.question = question;
    this.answers = new String[answers.length];
    this.regexAnswers = new String[answers.length];
    
    // For each answer, assign the value to this.answers
    for (int i = 0; i < answers.length; i++)
    {
      // Somewhat of a brute force solution, 
      // but Java never requires more than one space anyway
      this.answers[i] = answers[i];
      this.answers[i] = this.answers[i].replaceAll("#0#", "");
      this.answers[i] = this.answers[i].replaceAll("#0,1#", " ");
      this.answers[i] = this.answers[i].replaceAll("#1#", " ");
      this.regexAnswers[i] = answers[i];
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("\\(", "\\\\(");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("\\)", "\\\\)");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("\\.", "\\\\.");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("\\?", "\\\\?");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("\\*", "\\\\*");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("\\+", "\\\\+");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("#0(,1)?#", "(\\\\s*)");
      this.regexAnswers[i] = this.regexAnswers[i].replaceAll("#1#", "(\\\\s+)");
    }
    
//    System.arraycopy(answers, 0, this.answers, 0, this.answers.length);
    this.correct = correct;
    this.grouping = grouping;
  }  
  
  /**
   * Returns the question number of this ExamQuestion.
   * 
   * @return this.number An int containing the number of this ExamQuestion.
   * 
   */
  
  public int getNumber()
  {
    return this.number;
  }

  /**
   * Sets the question number of this ExamQuestion.
   * 
   * @param number The int to set the number of this ExamQuestion to.
   * 
   */
  
  public void setNumber(int number)
  {
    this.number = number;
  }

  /**
   * Returns the question of this ExamQuestion.
   * 
   * @return this.question The String containing the question of this ExamQuestion.
   * 
   */
  
  public String getQuestion()
  {
    return this.question;
  }

  /**
   * Sets the question of this ExamQuestion.
   * 
   * @param question The String to set the question of this ExamQuestion to.
   * 
   */
  
  public void setQuestion(String question)
  {
    this.question = question;
  }

  /**
   * Returns the possible answers to this ExamQuestion.
   * 
   * @return this.answers The String[] containing the answers to this ExamQuestion.
   * 
   */
  
  public String[] getAnswers()
  {
    return this.answers;
  }

  /**
   * Sets the possible answer to this ExamQuestion.
   * 
   * @param answers The String[] to set the answer to this ExamQuestion to.
   * 
   */
  
  public void setAnswers(String[] answers)
  {
    this.answers = answers;
  }

  /**
   * Returns the index of the correct answer to this ExamQuestion.
   * 
   * @return this.correct An int containing the index of the correct answer to this ExamQuestion.
   * 
   */
  
  public int getCorrect()
  {
    return this.correct;
  }

  /**
   * Sets the index of the correct answer to this ExamQuestion.
   * 
   * @param correct The int to set the index of the correct answer to this ExamQuestion to.
   * 
   */
  
  public void setCorrect(int correct)
  {
    this.correct = correct;
  }
  
  /**
   * Returns the grouping of this ExamQuestion.
   *
   * @return grouping The int containing the grouping of this ExamQuestion.
   *
   */
  
  public int getGrouping()
  {
    return this.grouping;
  }

  /**
   * Sets the grouping of this ExamQuestion.
   *
   * @param grouping The int containing the grouping to set for this ExamQuestion.
   *
   */
  
  public void setGrouping(int grouping)
  {
    this.grouping = grouping;
  }

  /**
   * Returns the correct answer to this ExamQuestion.
   * Since only one answer may be returned, fill-in-the-blank questions 
   * return the first correct answer.
   * 
   * @return correctAnswer A String containing the correct answer to this ExamQuestion.
   * 
   */
  
  public String getCorrectAnswer()
  {
    String correctAnswer = "";
    
    // If there is a valid answer, assign it to correctAnswer
    if ((0 <= this.correct) && (this.correct < this.answers.length))
    {
      correctAnswer = this.answers[this.correct];
    }
    // If this.correct is -1, then assume that the first answer is the correct answer
    else if (this.correct == -1)
    {
      correctAnswer = this.answers[0];
    }
    
    return correctAnswer;
  }
  
  /**
   * Determines if an answer is correct.
   * This should only be used for fill-in-the-blank questions; 
   * though it will work for multiple-choice, there is no easy way to get the "answer"
   * from a multiple-choice question, only the radio button that the user selected.
   * 
   * @param userAnswer A String containing the user answer to this question.
   * 
   * @return userCorrect A boolean that is true if the answer matches a correct answer,
   *                                       false otherwise.
   * 
   */
  
  public boolean isCorrect(String userAnswer)
  {
    boolean userCorrect = false;
    
    // If fill-in-the-blank, then this.correct is -1
    if (this.correct == -1)
    {
      // Check if any of the answers match the user answer
      // If so, indicate that the user was correct
      for (int i = 0; i < this.regexAnswers.length; i++)
      {
        if (userAnswer.trim().matches(this.regexAnswers[i]))
        {
          userCorrect = true;
        }
      }
    }
    // Else multiple choice
    else
    {
      if (userAnswer.equalsIgnoreCase(this.answers[this.correct]))
      {
        userCorrect = true;
      }
    }
    
    return userCorrect;
  }
}
